﻿
Imports System.Threading

Namespace atomic
    Public Module _atomic
        Private ReadOnly x86 As Boolean = False
        Private ReadOnly amd64 As Boolean = False

        Sub New()
            x86 = (IntPtr.Size() = 32 / bitcountInByte)
            amd64 = (IntPtr.Size() = 64 / bitcountInByte)
            Console.Error.WriteLine(strcat("processor architecture x86 = ", x86, ", amd64 = ", amd64))
        End Sub

        Public Sub eva(Of T As Class)(ByRef i As T, ByVal j As T)
            If x86 OrElse amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As Double, ByVal j As Double)
            'based on atomTests.doubleAtomTest, seems on x86, it's also safe
            'but since double is seldomly used, to make it really safe
            If amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As Int32, ByVal j As Int32)
            If x86 OrElse amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As Int64, ByVal j As Int64)
            If amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Sub eva(ByRef i As IntPtr, ByVal j As IntPtr)
            Thread.VolatileWrite(i, j)
        End Sub

        Public Sub eva(ByRef i As Object, ByVal j As Object)
            Interlocked.Exchange(i, j)
        End Sub

        Public Sub eva(ByRef i As Single, ByVal j As Single)
            If x86 OrElse amd64 Then
                Thread.VolatileWrite(i, j)
            Else
                Interlocked.Exchange(i, j)
            End If
        End Sub

        Public Function read(ByRef i As Int64) As Int64
            If amd64 Then
                Return Thread.VolatileRead(i)
            Else
                Return Interlocked.Read(i)
            End If
        End Function

        Public Function read(ByRef i As Int32) As Int32
            If x86 OrElse amd64 Then
                Return Thread.VolatileRead(i)
            Else
                'no support in .net framework for cpu <32 bit
                Return Thread.VolatileRead(i)
            End If
        End Function

        Public Function read(Of T As Class)(ByRef i As T) As T
            If x86 OrElse amd64 Then
                Return Thread.VolatileRead(i)
            Else
                'no support in .net framework for cpu <32 bit
                Return Thread.VolatileRead(i)
            End If
        End Function
    End Module
End Namespace
